﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;

namespace BadHabit.Factory.Tail {

    public class BaseHook {


        protected static string Repository { get; set; }
        protected static string Transaction { get; set; }
        protected static int Revision { get; set; }

        protected static FactoryService.ProjectService service = new BadHabit.Factory.Tail.FactoryService.ProjectService();

        protected static FactoryService.FactorySOAPHeader SOAPHeader = new BadHabit.Factory.Tail.FactoryService.FactorySOAPHeader();

        private static List<string> ignoreList;


        protected static List<string> IgnoreList {
            get {
                if (ignoreList != null)
                    return ignoreList;

                ignoreList = new List<string>();
                string ignoreString = Properties.Settings.Default.IgnoreTailFor;
                if (ignoreString == null)
                    return ignoreList;

                string[] ignoresExtensions = ignoreString.Split(new char[] { ' ' });
                ignoreList.AddRange(ignoresExtensions);

                return ignoreList;
            }
        }


        protected static string RepositoryName {
            get {
                return Repository.Substring(Repository.LastIndexOf("/"));
            }
        }

        
        protected static void SetFactoryServer() {
            service.Url = GetFactoryServer();
            service.PreAuthenticate = true;
            service.Credentials = System.Net.CredentialCache.DefaultCredentials;
            FactoryService.FactorySOAPHeader SOAPHeader = new BadHabit.Factory.Tail.FactoryService.FactorySOAPHeader();
            SOAPHeader.FactoryClientMinVersion = "factoryTail";
            service.FactorySOAPHeaderValue = SOAPHeader;   
        }

        protected static bool GetResolveTaskNumber() {
            return Properties.Settings.Default.ResolveTaskNumber;
        }

        protected static string GetFactoryServer() {            
            return Properties.Settings.Default.FactoryServerUrl + "/ProjectService.asmx";
        }

        protected static string GetRepositoryUrl() {
            return Properties.Settings.Default.RepositoryUrl;
        }


        protected static string[] GetFilesChanged() {
            if (Properties.Settings.Default.UseSVNLog)
                return GetFilesChangedBySVNLog();

            return GetFilesChangedBySVNLook();
        }

        protected static string[] GetFilesChangedBySVNLook() {
            System.Diagnostics.Process shell = new System.Diagnostics.Process();

            shell.StartInfo.FileName = Properties.Settings.Default.SVNBinPath + "\\svnlook.exe";
            shell.StartInfo.Arguments = "changed -r " + Revision + " \"" + Repository + "\"";

            shell.StartInfo.StandardOutputEncoding = Encoding.GetEncoding(858);
            shell.StartInfo.UseShellExecute = false;
            shell.StartInfo.RedirectStandardOutput = true;
            shell.Start();



            string transactionInfo = shell.StandardOutput.ReadToEnd();
        
            string[] files = transactionInfo.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
            for (int i = 0; i < files.Length; i++) {
                files[i] = files[i].Replace("\r", "");
                files[i] = files[i] + shell.StandardOutput.CurrentEncoding.WindowsCodePage.ToString() + " " + shell.StandardOutput.CurrentEncoding.EncodingName + " " + shell.StandardOutput.CurrentEncoding.CodePage;
                if (files[i].Length > 4)
                    files[i] = files[i].Substring(4);
            }
            return files;
        }

        protected static string[] GetFilesChangedBySVNLog() {
            System.Diagnostics.Process shell = new System.Diagnostics.Process();

            shell.StartInfo.FileName = Properties.Settings.Default.SVNBinPath + "\\svn.exe";

            shell.StartInfo.Arguments = "log -r " + Revision + " -v --xml --username " + Properties.Settings.Default.SVNUser + "  --password " + Properties.Settings.Default.SVNPassword + "  \"" + GetRepositoryUrl() + "\"";
            
            
            shell.StartInfo.UseShellExecute = false;
            shell.StartInfo.StandardOutputEncoding = Encoding.UTF8;
            shell.StartInfo.RedirectStandardOutput = true;

            shell.StartInfo.RedirectStandardError = true;

            shell.Start();
            
            string transactionInfo = shell.StandardOutput.ReadToEnd();

            
            return GetFilesFromXML(transactionInfo);
            

        }


        private static string[] GetFilesFromXML(string xml) {

            
            XmlDocument doc = new XmlDocument();
            doc.InnerXml = xml;

            XmlNodeList paths = doc.GetElementsByTagName("path");
            
            if (paths == null)
                return new string[0];

            string[] files = new string[paths.Count];
            for (int i = 0; i < files.Length; i++)
                files[i] = paths[i].InnerText;

            return files;
        }

        protected static string[] CleanFileList(string[] files) {
            List<string> cleanList = new List<string>();
            for (int i = 0; i < files.Length; i++) {
                if (!IgnoreList.Contains(GetArtifactExtension(files[i]))) 
                    cleanList.Add(files[i]);
            }

            return cleanList.ToArray();

        }

        protected static string GetComment() {
            System.Diagnostics.Process shell = new System.Diagnostics.Process();
            
            shell.StartInfo.FileName = Properties.Settings.Default.SVNBinPath + "\\svnlook.exe";
            shell.StartInfo.Arguments = "log -t " + Transaction + " \"" + Repository + "\"";
            shell.StartInfo.UseShellExecute = false;
            shell.StartInfo.RedirectStandardOutput = true;
            shell.Start();
            string transactionInfo = shell.StandardOutput.ReadToEnd();
            return transactionInfo;
        }

        protected static string SetComment(string newComment) {
            System.Diagnostics.Process shell = new System.Diagnostics.Process();

            shell.StartInfo.FileName = Properties.Settings.Default.SVNBinPath + "\\svn.exe";
            string arg = "propset --username " + Properties.Settings.Default.SVNUser + " --password " + Properties.Settings.Default.SVNPassword + " --revprop -r " + Revision + " svn:log \"" + newComment + "\" \"" + GetRepositoryUrl() + "\"";            
            shell.StartInfo.Arguments = arg;          

            shell.StartInfo.UseShellExecute = false;
            shell.StartInfo.RedirectStandardOutput = true;
            shell.Start();
            string transactionInfo = shell.StandardOutput.ReadToEnd();
            return transactionInfo;
        }

        protected static string GetCommentByRevision() {
            System.Diagnostics.Process shell = new System.Diagnostics.Process();

            shell.StartInfo.FileName = Properties.Settings.Default.SVNBinPath + "\\svnlook.exe";
            shell.StartInfo.Arguments = "log -r " + Revision + " \"" + Repository + "\"";
            shell.StartInfo.UseShellExecute = false;
            shell.StartInfo.RedirectStandardOutput = true;
            shell.Start();
            string transactionInfo = shell.StandardOutput.ReadToEnd();
            return transactionInfo;
        }

        protected static string GetMadeByUser() {
            System.Diagnostics.Process shell = new System.Diagnostics.Process();

            shell.StartInfo.FileName = Properties.Settings.Default.SVNBinPath + "\\svnlook.exe";            
            shell.StartInfo.Arguments = "info -t " + Transaction + " \"" + Repository + "\"";
            shell.StartInfo.UseShellExecute = false;
            shell.StartInfo.RedirectStandardOutput = true;
            
            shell.Start();
            
            string transactionInfo = shell.StandardOutput.ReadToEnd();
            string user = transactionInfo.Split('\n')[0];
            return user.Replace("\r", "");
        }

        protected static string GetMadeByUserByRevision() {
            System.Diagnostics.Process shell = new System.Diagnostics.Process();

            shell.StartInfo.FileName = Properties.Settings.Default.SVNBinPath + "\\svnlook.exe";
            shell.StartInfo.Arguments = "info -r " + Revision + " \"" + Repository + "\"";
            shell.StartInfo.UseShellExecute = false;
            shell.StartInfo.RedirectStandardOutput = true;
            shell.Start();
            string transactionInfo = shell.StandardOutput.ReadToEnd();
            string user = transactionInfo.Split('\n')[0];
            return user.Replace("\r", "");
        }



        protected static int GetTaskId(string comment) {
            int taskId = -1;
            int idxStart = comment.IndexOf('#');
            if (idxStart < 0)
                return taskId;
            int idxEnd = comment.IndexOf('#', idxStart + 1);
            if (idxEnd < 0)
                return taskId;

            Int32.TryParse(comment.Substring(idxStart + 1, idxEnd - idxStart - 1), out taskId);

            return taskId;
        }

        protected static bool IsTailed(string comment) {
            return (comment.ToUpper().IndexOf("#NOTAIL#") < 0);
        }


        /// <summary>
        /// Gets a artifact file extension.
        /// </summary>
        /// <param name="artifactPath">The artifact path</param>
        /// <returns>The file extension</returns>
        private static string GetArtifactExtension(string artifactPath) {
            
            string artifactName = artifactPath;
            if (artifactPath.Contains('/'))
                artifactName = artifactPath.Substring(artifactPath.LastIndexOf('/'));

            if (artifactName.IndexOf('.') == -1)
                return String.Empty;
            
            return artifactName.Substring(artifactName.IndexOf('.'));
        }



        
        
    }
}
